package com.exp.bookhouse.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exp.bookhouse.mapper.UserMapper;
import com.exp.bookhouse.pojo.MyUser;
import com.exp.bookhouse.pojo.Role;
import com.exp.bookhouse.service.UserService;
import com.exp.bookhouse.util.AesCbcUtil;
import com.exp.bookhouse.util.HttpClientUtil;
import com.exp.bookhouse.util.UploadService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 */
@PropertySource(value = "classpath:message.properties")
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private PasswordEncoder passwordEncoder;





    //加密正则
    private Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}");

    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.secret}")
    private String secret;
    @Value("${wx.grant_type}")
    private String grantType;
    @Value("${wx.url}")
    private String url;
    @Value("${wx.password}")
    private String password;

    @Value("${nginx.port}")
    private String port;
    @Value("${nginx.host}")
    private String host;
    @Value("${nginx.group}")
    private String group;

    @Value("${myUser.headImage}")
    private String headImage;


    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    @Override
    public MyUser queryUserById(Long id) {
        return userMapper.selectById(id);
    }

    /**
     * 微信登录
     * @param encryptedData 明文,加密数据
     * @param iv            加密算法的初始向量
     * @param code          code值五分钟限制
     * @return 返回用户信息
     * @throws Exception 登录失败
     */
    @Override
    public MyUser weChatLogin(String encryptedData, String iv, String code) throws Exception {
        Map<String, String> param = new HashMap<>(4);
        param.put("appid", appid);
        param.put("secret", secret);
        param.put("js_code", code);
        param.put("grant_type", grantType);

        //发送请求到微信服务器，获取openid和session_key
        String sr = HttpClientUtil.doGet(url, param);

        System.out.println("weChatLogin");

        // 判断获取的是否有值
        if (StringUtils.isBlank(sr)) {
            throw new Exception("获取微信数据失败");
        }
        //解析相应内容（转换成json对象）
        JSONObject json = JSONObject.parseObject(sr);

        System.out.println("+++++++++++++++++json+++++++++++++"+json);

        String openid = json.getString("openid");
        System.out.println("openid"+openid);
        MyUser myUser = queryUserByOpenid(openid);  //查询数据库该用户是否存在
        if (myUser != null) {     //存在直接返回
            return myUser;
        }
        //不存在就注册进去

        //获取会话密钥（session_key）
        String sessionKey = json.get("session_key").toString();
        //对encryptedData加密数据进行AES解密
        String result = AesCbcUtil.decrypt(encryptedData, sessionKey, iv, "UTF-8");

        if (StringUtils.isBlank(result)) {
            throw new RuntimeException("解析微信数据失败");
        }

        JSONObject userInfoJSON = JSONObject.parseObject(result);
        myUser = new MyUser();
        myUser.setOpenid(userInfoJSON.getString("openId"));
        myUser.setLoginUser(userInfoJSON.getString("nickName"));
        myUser.setHeadImage(userInfoJSON.getString("avatarUrl"));

        myUser.setStatus(1);
        //加密密码
        String secret  = new BCryptPasswordEncoder().encode(password);
        myUser.setPassword(secret);

        /* MyUser 使用的是回调 id */
        int isSave = saveUser(myUser);
        if (isSave == 0) {
            throw new RuntimeException("服务器忙碌，请等下再试");
        }
        return myUser;
    }

    /**
     * 更新用户信息
     * @param myUser
     * @return
     */
    @Override
    public int updateUser(MyUser myUser) {
        myUser.setUpdateTime(new Date());
        return userMapper.updateUser(myUser);
    }

    /**
     * 更新头像
     * @param userId
     * @param fullUrl
     * @return
     */
    @Override
    public int updateHeadImage(Long userId, String fullUrl) {
        return userMapper.updateHeadImage(userId,fullUrl);
    }

    /**
     * 分页查询用户信息
     * @param page
     * @param size
     * @return
     */
    @Override
    public IPage<MyUser> queryUserByPage(Integer page, Integer size) {
        IPage<MyUser> iPage = new Page<>(page,size);
        return userMapper.selectPage(iPage,null);
    }

    /**
     * 根据用户账号查询用户信息
     * @param loginName
     * @return
     */
    @Override
    public MyUser queryUserByLoginName(String loginName) {
        return userMapper.selectOne(new QueryWrapper<MyUser>().eq("login_user", loginName));
    }

    /**
     * 查询用户的角色信息
     * @param userId
     * @return
     */
    @Override
    public List<Role> queryRoles(Long userId) {
        return userMapper.queryRoles(userId);
    }

    /**
     * 查询用户可以添加的角色
     * @param userId
     * @return
     */
    @Override
    public List<Role> queryOtherRoles(Long userId) {
        return userMapper.queryOtherRoles(userId);
    }

    /**
     * 添加用户角色
     * @param userId
     * @param roleIds
     */
    @Override
    public void saveUserAddRole(Long userId, String[] roleIds) {
        for (String roleId : roleIds) {
            Long id = Long.parseLong(roleId);
            userMapper.saveUserRole(userId,id);
        }
    }

    /**
     * 添加用户
     * @param myUser
     * @param file
     */
    @Override
    public void saveUser(MyUser myUser, MultipartFile file) throws Exception {

        String fullUrl = "";
        if(file != null && file.getSize() > 0){
            fullUrl = uploadService.uploadFile(file);   //上传文件返回不带分组路径
//            fullUrl = "http://"+host+":"+port+"/"+group+"/"+path;   //全路径
        }else{  //默认头像
            fullUrl = headImage;
        }
        myUser.setHeadImage(fullUrl);

        //密码加密
        String secret  = new BCryptPasswordEncoder().encode(myUser.getPassword());
        myUser.setPassword(secret);
        userMapper.insert(myUser);
    }

    /**
     * 注册用户
     * @param myUser
     * @return
     */
    @Override
    public void register(MyUser myUser){
        myUser.setHeadImage(headImage);
        String secret  = new BCryptPasswordEncoder().encode(myUser.getPassword());
        myUser.setPassword(secret);
        myUser.setStatus(1);
        Role role = new Role();
        role.setRoleName("ROLE_ADMIN");
        myUser.setRoles(Arrays.asList(role));
        userMapper.insert(myUser);
    }

    /**
     * 更新用户信息
     * @param myUser
     * @param file
     */
    @Override
    public void updateUser(MyUser myUser, MultipartFile file) throws IOException {
        MyUser myUser1 = userMapper.selectById(myUser.getId());   //查询数据库的用户信息

        String fullUrl = "";
        if(file != null && file.getSize() > 0){
            fullUrl = uploadService.uploadFile(file);   //上传文件返回不带分组路径
//            fullUrl = "http://"+host+":"+port+"/"+group+"/"+path;   //全路径

            //删除服务器的图片
            if(myUser1.getHeadImage().isEmpty()){
                String[] split = myUser1.getHeadImage().split(".com/");
                uploadService.deleteFile(split[1]);
            }
        }else{  //原来的头像
            fullUrl = myUser1.getHeadImage();
        }
        myUser.setHeadImage(fullUrl);

        //加密密码，若密码已经加密则不再加密
        String secret;
        Matcher matcher = BCRYPT_PATTERN.matcher(myUser.getPassword());//正则匹配
        if(!matcher.matches()){
            secret  = new BCryptPasswordEncoder().encode(myUser.getPassword());
        }else {
            secret = myUser.getPassword();
        }
        myUser.setPassword(secret);
        //更新用户信息
        userMapper.updateById(myUser);
    }

    /**
     * 根据id删除用户
     * @param id 用户id
     */
    @Override
    public void deleteUser(Long id) {
        //删除用户-角色中间表
        userMapper.deleteUserRole(id);

        //删除用户
        userMapper.deleteById(id);
    }

    @Override
    public String changeAvatar(MultipartFile file, Long id) throws Exception {
        if(file == null || id == null) {
            throw new Exception("更新头像失败");
        }
        //删除图片
        MyUser myUser = userMapper.selectById(id);
        String headImage = myUser.getHeadImage();
        if(!StringUtils.isBlank(headImage) && headImage.contains(group)){
            String[] split = headImage.split(".com/");
            uploadService.deleteFile(split[1]);
        }
        //上传图片
        String fillUrl = uploadService.uploadFile(file);
//        String fillUrl = "http://"+host+":" + port + "/" + group + "/" + notGroupUrl;

        //更新用户头像
        MyUser myUser1 = new MyUser();
        myUser1.setId(myUser.getId());
        myUser1.setHeadImage(fillUrl);
        userMapper.updateById(myUser1);

        return fillUrl;
    }

    /**
     * 查询用户数量
     * @return
     */
    @Override
    public int queryCountUser() {
        return userMapper.selectCount(null);
    }


    /**
     * 保存用户信息
     * @param myUser
     * @return
     */
    private int saveUser(MyUser myUser) {
        return userMapper.insert(myUser);
    }


    /**
     *  根据openid查询用户
     * @param openid
     * @return
     */
    private MyUser queryUserByOpenid(String openid) {
        QueryWrapper<MyUser> wrapper = new QueryWrapper<>();
        wrapper.eq("openid",openid);
        return userMapper.selectOne(wrapper);
    }

    /**
     *  根据用户姓名模糊查询用户
     * @return
     */
    @Override
    public List<MyUser> searchByUserName(String userName){
        List<MyUser> user = new ArrayList<>();
        QueryWrapper<MyUser> wrapper = new QueryWrapper<>();
        wrapper.like("user_name",userName);
        user = userMapper.selectList(wrapper);
        return user;
    }

    /**
     *  查询所有用户
     * @return
     */
    @Override
    public List<MyUser> queryAllUser(){
        return userMapper.queryAllUser();
    }

}
